﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using SmartProject.Entity;
using SmartProject.Data;

using NUnit.Framework;

namespace SmartProject.Testing
{
    [TestFixture]
    public class Test05_FirstInitialAndLastNameUsername
    {
        [TestFixtureSetUp()]
        public void Start()
        {
            using (var session = DataProvider.Instance.Session)
            {
                Log.Debug(session, this, "Start", "Setting Business Rule.");
                using (var transaction = session.BeginTransaction())
                {
                    BusinessRulePreferences.Username userName = new BusinessRulePreferences.Username();
                    userName.SetSelectedBusinessRule(session, "First initial, last name username");
                    transaction.Commit();
                    transaction.Dispose();
                }
                Log.Debug(session, this, "Start", "Business Rule setup is complete.");
                session.Close();
                session.Dispose();
            }
        }

        [Test]
        public void Test01_AddUser()
        {
            using (var session = DataProvider.Instance.Session)
            {
                Log.Debug(session, this, "Test01_AddUser", "Begin Test01_AddUser");
                using (var transaction = session.BeginTransaction())
                {
                    User.NewUser(session, "David", "Lee", "dlee", "dlee@test.com", "Any", new string[] { "User" });
                    transaction.Commit();
                    transaction.Dispose();
                    Log.Debug(session, this, "Test01_AddUser", "David Lee is addeded");
                }
                session.Close();
                session.Dispose();
            }
        }


        [Test]
        public void Test02_AddSameUser()
        {
            using (var session = DataProvider.Instance.Session)
            {
                using (var transaction = session.BeginTransaction())
                {
                    User.NewUser(session, "David", "Lee", "dlee", "dlee2@test.com", "Any", new string[] { "User" });
                    transaction.Commit();
                    transaction.Dispose();
                }
                Assert.IsNotNull(User.GetUserByUsername(session, "dlee1"));
            }
        }

        [Test]
        public void Test03_UpdateUserFirstAndLastNames()
        {
            using (var session = DataProvider.Instance.Session)
            {
                User user = User.GetUserByUsername(session, "dlee");
                Assert.IsNotNull(user);
                user.FirstName = "Benjamin";
                user.LastName = "Chen";
                string originalEmail = user.Email;
                List<string> originalRoleNames = new List<string>();
                for (int i = 0; i < user.Roles.Count; i++)
                {
                    originalRoleNames.Add(user.Roles[i].Name);
                }
                using (var transaction = session.BeginTransaction())
                {
                    user.Save(session);
                    transaction.Commit();
                    transaction.Dispose();
                }
                Assert.IsNull(User.GetUserByUsername(session, "dlee"));
                user = User.GetUserByUsername(session, "bchen");
                Assert.AreEqual("Benjamin", user.FirstName);
                Assert.AreEqual("Chen", user.LastName);
                Assert.AreEqual("bchen", user.Username);
                Assert.AreEqual(originalEmail, user.Email);
                Assert.AreEqual(true, user.Active);
                Assert.AreEqual(originalRoleNames.Count, user.Roles.Count);
                Assert.IsNull(user.LastLogin);
                Assert.IsNull(user.LastLogout);

                for (int i = 0; i < originalRoleNames.Count; i++)
                {
                    string originalRoleName = originalRoleNames[i];
                    bool found = false;
                    for (int j = 0; j < user.Roles.Count; j++)
                    {
                        if (user.Roles[j].Name == originalRoleName)
                        {
                            found = true;
                            break;
                        }
                    }
                    Assert.IsTrue(found);
                }

                session.Close();
                session.Dispose();
            }
        }

        [Test]
        public void Test04_UpdateUserEmailAndFindByEmail()
        {
            using (var session = DataProvider.Instance.Session)
            {
                User user = User.GetUserByEmail(session, "dlee@test.com");
                Assert.IsNotNull(user);
                string originalFirstName = user.FirstName;
                string originalLastName = user.LastName;
                string originalUsername = user.Username;
                user.Email = "dlee3@test.com";
                List<string> originalRoleNames = new List<string>();
                for (int i = 0; i < user.Roles.Count; i++)
                {
                    originalRoleNames.Add(user.Roles[i].Name);
                }
                using (var transaction = session.BeginTransaction())
                {
                    user.Save(session);
                    transaction.Commit();
                    transaction.Dispose();
                }

                Assert.IsNull(User.GetUserByEmail(session, "dlee@test.com"));
                user = User.GetUserByEmail(session, "dlee3@test.com");
                Assert.IsNotNull(user);
                Assert.AreEqual(originalFirstName, user.FirstName);
                Assert.AreEqual(originalLastName, user.LastName);
                Assert.AreEqual(originalUsername, user.Username);
                Assert.AreEqual("dlee3@test.com", user.Email);
                Assert.AreEqual(true, user.Active);
                Assert.AreEqual(originalRoleNames.Count, user.Roles.Count);
                Assert.IsNull(user.LastLogin);
                Assert.IsNull(user.LastLogout);

                for (int i = 0; i < originalRoleNames.Count; i++)
                {
                    string originalRoleName = originalRoleNames[i];
                    bool found = false;
                    for (int j = 0; j < user.Roles.Count; j++)
                    {
                        if (user.Roles[j].Name == originalRoleName)
                        {
                            found = true;
                            break;
                        }
                    }
                    Assert.IsTrue(found);
                }

                session.Close();
                session.Dispose();
            }
        }

        [Test]
        public void Test06_RemoveUser()
        {
            using (var session = DataProvider.Instance.Session)
            {
                User bChen = User.GetUserByUsername(session, "bchen");
                Assert.IsNotNull(bChen);
                User dlee1 = User.GetUserByUsername(session, "dlee1");
                Assert.IsNotNull(dlee1);
                using (var transaction = session.BeginTransaction())
                {
                    bChen.Remove(session);
                    dlee1.Remove(session);
                    transaction.Commit();
                    transaction.Dispose();
                }
                Assert.IsNull(User.GetUserByUsername(session, "dlee"));
                Assert.IsNull(User.GetUserByUsername(session, "dlee2"));
                Assert.IsNull(User.GetUserByUsername(session, "bchen"));
                session.Close();
                session.Dispose();
            }
        }

        [Test]
        public void Test07_DeleteUser()
        {
            using (var session = DataProvider.Instance.Session)
            {
                using (var transaction = session.BeginTransaction())
                {
                    User.Clean(session);
                    transaction.Commit();
                    transaction.Dispose();
                }
                session.Close();
                session.Dispose();
            }
        }
    }
}
